package c_lianbiao;

import java.util.Iterator;
import java.util.function.Consumer;

/**
 * @ClassName A_DanXiangLianBiao
 * @Description
 * @Author Zhang Li Tao
 * @Date 2024/4/5
 * @Version 1.0
 **/
public class A_DanXiangLianBiao implements Iterable<Integer> {
    // 定义头结点
    private Node head = null;

    // 定义节点对象
    private class Node {
        int value; // 当前节点存储值
        Node next; // 当前节点的下一节点

        // 构造方法 记录存储值和下一节点
        public Node(int value, Node next) {
            this.value = value;
            this.next = next;
        }
    }

    // 插入头部 新增的对象变成头结点 俗称头插法
    public void addFirst(int value) {
        // 当前头结点变成当前节点的下一节点 自己变成头结点
        this.head = new Node(value, this.head);
    }

    // 找到链表中最后一个元素 这里单独抽取是为了后续可能还要用
    private Node findLast() {
        // 如果head节点为null 则说明还没有插入元素
        if (head == null) {
            return null;
        }

        Node currentIndexNode = head;

        while (currentIndexNode.next != null) {
            currentIndexNode = currentIndexNode.next;
        }

        return currentIndexNode;
    }

    // 插入尾部 新增的对象变成尾节点 俗称尾插法
    public void addLast(int value) {
        // 找到链表中最后一个元素 然后创建新节点变成其的next成为尾节点
        Node lastNode = findLast();

        // 最后一个元素为null 说明链表中还没有元素 需要首次addFirst
        if (lastNode == null) {
           addFirst(value);
           return;
        }

        // 最后一个节点的下一节点本来为null 现在变为新节点 然后新节点尾节点为null
        lastNode.next = new Node(value, null);
    }

    // 尾部插入多个元素 分成两个形参 以value打头 values后续接上 成待插入链表再插
    public void addLast(int value, int... values) {
        // 形参1作为待插入链表的头结点
        Node smallListHead = new Node(value, null);

        // 当前指针节点 和操作数组的滑动边界一个道理
        Node currentIndexNode = smallListHead;

        for (int smallListValue : values) {
            // 创建出新节点 加到当前指针节点的next
            currentIndexNode.next = new Node(smallListValue, null);
            // 指针后移一位 继续循环串起后续节点
            currentIndexNode = currentIndexNode.next;
        }

        Node lastNode = findLast();
        // 如果尾节点为null 则直接通过head直接灌入待插入链表
        if (lastNode == null) {
            head = smallListHead;
            return;
        }

        // 不为null 则待插入链表的头节点放到尾节点的next上
        lastNode.next = smallListHead;
    }

    // 根据索引查找节点
    public Node findNode(int index) {

        return null;
    }

    // 获取对应索引上的值
    public int get(int index) {

        return 0;
    }

    // 指定位置插入元素
    public void insert(int index, int value) {

    }

    // 指定位置删除元素
    public void remove(int index) {

    }

    // 遍历 while
    public void loopByWhile(Consumer<Integer> consumer) {
        Node currentIndexNode = head;

        while (currentIndexNode != null) {
            consumer.accept(currentIndexNode.value);
            currentIndexNode = currentIndexNode.next;
        }
    }

    // 遍历 for
    public void loopByFor(Consumer<Integer> consumer) {
        for (Node currentIndexNode = head; currentIndexNode != null; currentIndexNode = currentIndexNode.next) {
            consumer.accept(currentIndexNode.value);
        }
    }

    // Iterable迭代
    @Override
    public Iterator<Integer> iterator() {

        return new Iterator() {
            Node currentIndexNode = head;

            @Override
            public boolean hasNext() {
                return currentIndexNode != null;
            }

            @Override
            public Integer next() {
                int currentValue = currentIndexNode.value;
                currentIndexNode = currentIndexNode.next;
                return currentValue;
            }
        };
    }

    public static void main(String[] args) {
        A_DanXiangLianBiao list = new A_DanXiangLianBiao();
//        list.addFirst(2);
//        list.addFirst(3);

        list.addLast(1, 2, 3, 4);

//        list.loopByWhile(i -> System.out.println(i));
//        list.loopByFor(i -> System.out.println(i));
        for (Integer value : list) {
            System.out.println(value);
        }

        Node last = list.findLast();
        System.out.println(last.value);
    }
}
